
#include "User_App.h"
#include "./flash/flash_eeprom.h"
#include "./flash/stm32g0xx_ll_flash.h"
#include "string.h"

const uint32_t Fml_Constant = 0x12211001; // 用户指定的32位常数
uint8_t *C = (uint8_t *)&Fml_Constant;
uint8_t D[12]; // D[12]为公式的输入数组(注意与ID[12]区分).
uint8_t Result[4];
uint32_t Decode_Data;

psswd_TypeDef psswd;

uint8_t DataBuf[2048];
uint32_t Flash_Addr;

uint8_t Flash_write_NE(uint32_t Addr, uint64_t *Data, uint16_t Num)
{
    uint8_t err = 0;
    LL_Flash_Unlock();
    for (uint16_t i = 0; i < Num; i++)
    {
        LL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Addr + i * 8, Data[i]);
    }
    LL_Flash_lock();
    return err;
}

uint8_t Flash_Read(uint32_t Addr)
{
    return *(__IO uint8_t *)Addr;
}
extern uint8_t Encipherment(void);
// OPT_Data_Typedef OPT_Data;

uint32_t Flash_Test;
void App_Decode(void)
{
    uint32_t err;
    uint64_t Tmp = *((uint64_t *)APP_DECODE_ADDR);
    FLASH_EraseInitTypeDef pEraseInit;
    if (Tmp == 0xffffffffffffffff)
    {
        while (Encipherment())
        {
        };
        __disable_irq();

        LL_Flash_Unlock();
        pEraseInit.Banks = FLASH_BANK_1;
        pEraseInit.NbPages = 1;
        pEraseInit.Page = (FLASH_USER_START_ADDR - FLASH_BASE) / FLASH_PAGE_SIZE;
        pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
        LL_FLASHEx_Erase(&pEraseInit, &err);
        //  EraseSector(FLASH_USER_START_ADDR);

        LL_Flash_lock();

        __enable_irq();

        //		for(uint8_t i = 0 ; i < 6 ; i++){
        //			LL_mDelay(50);
        //		}
        //		OPT_data_StructInit(&OPT_Data);
        //		OPT_Data.optr &= ~(0xff);
        //		OPT_Data.optr |= 0x88;
        //		OPT_Flash_Unlock();
        //		OPT_EraseChip();
        //		OPT_ProgramPage(FLASH_OPTION_ADDR,&OPT_Data);
        //		OPT_Flash_lock();
        //
    }

    Get_UID();
    Flash_Test = FLASH_EEPROM_Read(0x01);

    while (1)
    {
        // LL_mDelay(1000);
        Flash_Test++;
        FLASH_EEPROM_Write(0x01, Flash_Test);
        if (Flash_Test != FLASH_EEPROM_Read(0x01))
        {
            while (1)
            {
            }
        }
    }
}

void Get_UID(void)
{
    psswd.ID_WORD[0] = *(__IO uint32_t *)(0x1FFF7590);
    psswd.ID_WORD[1] = *(__IO uint32_t *)(0x1FFF7590 + 4);
    psswd.ID_WORD[2] = *(__IO uint32_t *)(0x1FFF7590 + 8);

    D[0] = psswd.ID_Byte[3];
    D[1] = psswd.ID_Byte[0];
    D[2] = psswd.ID_Byte[1];
    D[3] = psswd.ID_Byte[2];
    D[4] = psswd.ID_Byte[6];
    D[5] = psswd.ID_Byte[4];
    D[6] = psswd.ID_Byte[7];
    D[7] = psswd.ID_Byte[5];
    D[8] = psswd.ID_Byte[11];
    D[9] = psswd.ID_Byte[8];
    D[10] = psswd.ID_Byte[10];
    D[11] = psswd.ID_Byte[9];
    Result[0] = C[0] + D[0] - D[4] + D[8];
    Result[1] = ((C[1] & D[1]) ^ D[5]) | D[9];
    Result[2] = C[2] | (D[2] ^ D[6] ^ D[10]);
    Result[3] = C[3] - D[3] + D[7] & D[11];
}
uint8_t get_0(void)
{
    uint8_t i, sum = 0;
    union
    {
        uint32_t Decode_Data;
        uint8_t Buf[4];
    } Decode;
    Decode.Decode_Data = *((uint32_t *)APP_DECODE_ADDR);

    for (i = 0; i < 4; i++)
    {
        sum += Result[i] ^ Decode.Buf[i];
    }

    return sum; //
}
uint8_t get_1(void)
{
    uint8_t i, sum = 0;
    union
    {
        uint32_t Decode_Data;
        uint8_t Buf[4];
    } Decode;
    Decode.Decode_Data = *((uint32_t *)APP_DECODE_ADDR);

    for (i = 0; i < 4; i++)
    {
        sum += Result[i] ^ Decode.Buf[i];
    }

    return sum ^ 1;
}

uint8_t check(void)
{
    uint8_t i;
    union
    {
        uint32_t Decode_Data;
        uint8_t Buf[4];
    } Decode;
    Decode.Decode_Data = *((uint32_t *)APP_DECODE_ADDR);

    for (i = 0; i < 4; i++)
    {
        if (Result[i] != Decode.Buf[i])
        {
            return 1;
        };
    }

    return 0;
}

uint64_t EEPromBUF[EEPROM_MAX_INDEX];
int64_t FLASH_EEPROM_Read(uint8_t addr)
{
    if (addr >= EEPROM_MAX_INDEX)
    {
        return -1;
    }

    uint16_t Flash_Cnt = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / 8;
    uint64_t *FlashData = (uint64_t *)FLASH_USER_START_ADDR;

    for (int16_t i = Flash_Cnt - 1; i >= 0; i--)
    {
        if ((FlashData[i] >> 48) == addr)
        {
            return FlashData[i] & 0xFFFFFFFF;
        }
    }

    return -1;
}

int8_t FLASH_EEPROM_Write(uint8_t addr, uint32_t data)
{
    uint32_t err;
    if (addr >= EEPROM_MAX_INDEX)
    {
        return -1;
    }

    uint16_t Flash_Cnt = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / 8;
    uint64_t *FlashData = (uint64_t *)FLASH_USER_START_ADDR;
    volatile uint64_t Tmp64;

    for (uint16_t i = 0; i < Flash_Cnt; i++)
    {
        if (FlashData[i] == 0xFFFFFFFFFFFFFFFF)
        {
            Tmp64 = ((uint64_t)addr << 48) | data;
            __disable_irq();
            LL_Flash_Unlock();
            LL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (i * 8 + FLASH_USER_START_ADDR), Tmp64);
            LL_Flash_lock();
            __enable_irq();
            return 0;
        }
    }

    uint8_t ReadIndex = 0;
    int64_t DatTmp;

    for (uint16_t i = 0; i < EEPROM_MAX_INDEX; i++)
    {
        DatTmp = FLASH_EEPROM_Read(i);

        if (DatTmp > 0 && DatTmp <= 0xFFFFFFFF)
        {
            if (i == addr)
            {
                EEPromBUF[ReadIndex] = ((uint64_t)i << 48) | data;
            }
            else
            {
                EEPromBUF[ReadIndex] = ((uint64_t)i << 48) | DatTmp;
            }
            ReadIndex++;
        }
    }

    __disable_irq();
    LL_Flash_Unlock();
    FLASH_EraseInitTypeDef pEraseInit;
    pEraseInit.Banks = FLASH_BANK_1;
    pEraseInit.NbPages = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / 0x800;
    pEraseInit.Page = (FLASH_USER_START_ADDR - FLASH_BASE) / FLASH_PAGE_SIZE;
    pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
    LL_FLASHEx_Erase(&pEraseInit, &err);
    for (uint16_t i = 0; i < ReadIndex; i++)
    {
        LL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (i * 8 + FLASH_USER_START_ADDR), EEPromBUF[i]);
    }
    LL_Flash_lock();
    __enable_irq();
    return 0;
}


